Ext.data.JsonReader = function( meta, recordType )
{
	meta = meta || {};
	
	Ext.applyIf(meta,
	{
		idProperty: 'id',
		successProperty: 'success',
		totalProperty: 'total'
	});

	Ext.data.JsonReader.superclass.constructor.call(this, meta, recordType || meta.fields);
};
Ext.extend(Ext.data.JsonReader, Ext.data.DataReader,
{
	read: function( response )
	{
		var json = response.responseText;
		var o = Ext.decode(json);
		if( !o )
		{
			throw
			{
				message: 'JsonReader.read: Json object not found'
			};
		}
		return this.readRecords(o); // 通过readRecords函数解析为二维表数据
	},

	// 解析后台来的JSON数据
	readResponse: function( action, response )
	{
		var o = (response.responseText !== undefined) ? Ext.decode(response.responseText) : response;// 解析JSON
		if( !o )
		{
			throw new Ext.data.JsonReader.Error('response');
		}

		var root = this.getRoot(o), success = this.getSuccess(o);
		
		// 成功，对于创建和更新数据，其data数据部分不能为空，至少应该返回id
		if( success && action === Ext.data.Api.actions.create )
		{
			var def = Ext.isDefined(root);
			
			// root为空
			if( def && Ext.isEmpty(root) )
			{
				throw new Ext.data.JsonReader.Error('root-empty', this.meta.root);
			}
			// 没有定义root
			else if( !def )
			{
				throw new Ext.data.JsonReader.Error('root-undefined-response', this.meta.root);
			}
		}

		// instantiate response object
		var res = new Ext.data.Response(
		{
			action: action,
			success: success,
			data: (root) ? this.extractData(root, false) : [],
			message: this.getMessage(o),
			raw: o
		});

		// blow up if no successProperty
		if( Ext.isEmpty(res.success) )
		{
			throw new Ext.data.JsonReader.Error('successProperty-response', this.meta.successProperty);
		}
		return res;
	},

	// 将原始数据解析为二维表数据
	readRecords: function( o )
	{
		this.jsonData = o; // 通过jsonData能获取到解析之前的JSON数据
		if( o.metaData ) // 原始数据中带有元数据
		{
			this.onMetaChange(o.metaData);
		}
		var s = this.meta, Record = this.recordType, f = Record.prototype.fields, fi = f.items, fl = f.length, v;

		var root = this.getRoot(o), c = root.length, totalRecords = c, success = true;
		
		// 如果有totalProperty的话
		if( s.totalProperty )
		{
			v = parseInt(this.getTotal(o), 10);
			if( !isNaN(v) )
			{
				totalRecords = v;
			}
		}
		
		// 如果有successProperty的话，那么
		if( s.successProperty )
		{
			v = this.getSuccess(o);
			if( v === false || v === 'false' )
			{
				success = false;
			}
		}

		// 解析成功后，返回给store
		// readResponse还没有实现，作者咋想的
		return {
			success: success,
			records: this.extractData(root, true), // <-- true to return [Ext.data.Record]
			totalRecords: totalRecords
		};
	},

	// 组织获取各个属性的函数
	buildExtractors: function()
	{
		// 每列数据进行转换的函数集合，存在就不需要构建
		if( this.ef )
		{
			return;
		}
		var s = this.meta, // 元数据
		Record = this.recordType, // 记录类型
		f = Record.prototype.fields,  // 所有表列
		fi = f.items, 
		fl = f.length;

		if( s.totalProperty ) // 取得原始数据中总数据内容的总条数，主要用于分页
		{
			this.getTotal = this.createAccessor(s.totalProperty); // 构建getTotal函数
		}
		if( s.successProperty ) // 取得原始数据中成功的标识值
		{
			this.getSuccess = this.createAccessor(s.successProperty);
		}
		if( s.messageProperty )
		{
			this.getMessage = this.createAccessor(s.messageProperty);
		}
		// 取得原始数据中的data数据部分，若没有指定root元数据，则采用整个json对象最为数据部分
		// new Ext.data.Store({root:'rows',totalProperty:'total',successProperty:'success',idProperty:'id'})
		this.getRoot = s.root ? this.createAccessor(s.root) : function( p )
		{
			return p;
		};
		if( s.id || s.idProperty )
		{
			// 先根据元数据id，找到data数据部分某行中的id值
			var g = this.createAccessor(s.id || s.idProperty);
			
			// 根据data数据部分制定行（记录）来找到该行的id值
			this.getId = function( record )
			{
				var r = g(record);
				return (r === undefined || r === '') ? null : r;
			};
		}
		else
		{
			// 元数据中没有指定，则采用null值
			this.getId = function()
			{
				return null;
			};
		}
		
		// 每列数据进行转换的函数集合，存在就不需要构建
		var ef = [];
		
		// ---->>fl is fields -->> [{name:'username',type:'string'},{name:'age',type:'int'}]
		
		for( var i = 0; i < fl; i++ )
		{
			f = fi[i]; // {name:'username',type:'string',mapping:'User'}
			// 取得该列与原始数据的data部分的数据之间的映射，没有制定mapping，则采用其name来进行
			var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
			
			// 构建每列的mapping映射函数，通过该函数来对每行数据进行查找，找到与该列相交的单元格的数据
			ef.push(this.createAccessor(map));
		}
		this.ef = ef;
	},

	/**
	 * @ignore TODO This isn't used anywhere?? Don't we want to use this where possible instead of complex #createAccessor?
	 */
	simpleAccess: function( obj, subsc )
	{
		return obj[subsc];
	},

	/**
	 * @ignore
	 */
	createAccessor: function()
	{
		var re = /[\[\.]/; // 点串的取值
		
		// obj[name] or obj.name
		
		return function( expr ) // total
		{
			// 如果传入值为空，返回空函数
			if( Ext.isEmpty(expr) )
			{
				return Ext.emptyFn;
			}
			// 如果传入值是个函数，那么直接返回
			if( Ext.isFunction(expr) )
			{
				return expr;
			}
			
			// 检测是否有.或者[，如果传入的是rows[root]
			var i = String(expr).search(re);
			if( i >= 0 )
			{
				// 返回 new function (obj) {return obj.rows[root]}
				return new Function('obj', 'return obj' + (i > 0 ? '.' : '') + expr);
			}
			
			// 如果没有.也没有[
			return function( obj )
			{
				return obj[expr];
			};

		};
	}(),

	// 通过mapping映射来获取每个对应值
	// [{username:'hhstuhacker',age:11},{username:'abc',age:99}]
	extractValues: function( data, items, len ) // data:原始数据中每行数据
	{
		var f, values = {};
		for( var j = 0; j < len; j++ ) // 每列
		{
			f = items[j]; // 单个item ---->>>>{username:'hhstuhacker',age:11}
			// 找到该列的mapping映射函数，传入改行数据，得出该单元格值
			// this.ef[j] 映射函数
			var v = this.ef[j](data); //v ---->> hhstuhacker ---->>>11
			// 对获得的单元格值进行类型转换
			values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, data);
		}
		return values; // 返回该行mapping且转换之后的数据
	}
});

/**
 * @class Ext.data.JsonReader.Error Error class for JsonReader
 */
Ext.data.JsonReader.Error = Ext.extend(Ext.Error,
{
	constructor: function( message, arg )
	{
		this.arg = arg;
		Ext.Error.call(this, message);
	},
	name: 'Ext.data.JsonReader'
});
Ext.apply(Ext.data.JsonReader.Error.prototype,
{
	lang:
	{
		'response': 'An error occurred while json-decoding your server response',
		'successProperty-response': 'Could not locate your "successProperty" in your server response.  Please review your JsonReader config to ensure the config-property "successProperty" matches the property in your server-response.  See the JsonReader docs.',
		'root-undefined-config': 'Your JsonReader was configured without a "root" property.  Please review your JsonReader config and make sure to define the root property.  See the JsonReader docs.',
		'idProperty-undefined': 'Your JsonReader was configured without an "idProperty"  Please review your JsonReader configuration and ensure the "idProperty" is set (e.g.: "id").  See the JsonReader docs.',
		'root-empty': 'Data was expected to be returned by the server in the "root" property of the response.  Please review your JsonReader configuration to ensure the "root" property matches that returned in the server-response.  See JsonReader docs.'
	}
});
